<template>
  <div class="text-img">
    <!-- 配置栏 -->
    <form class="text-img-operate">
      <label for="text-content">
        展示文字
        <input id="text-content" v-model.trim="textStr" type="text" @keydown.enter="drawer()">
      </label>

      <label for="text-increase">
        放大倍数
        <input id="text-increase" v-model.trim.number="textSize" type="number" @keydown.enter="drawer()">
      </label>

      <button type="button" @click="drawer()">
        绘制
      </button>
    </form>

    <!-- 图像展示 -->
    <div class="text-img-show">
      <canvas id="text-img-canvas" />
    </div>
  </div>
</template>


<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { imgComponent } from '@/types/shimNamespace'

const FONT_SIZE = 100
const DIFF = 4

let showCanvas: HTMLCanvasElement
let cacheCanvas: HTMLCanvasElement

let showCTX: CanvasRenderingContext2D
let cacheCTX: CanvasRenderingContext2D

const canvasSize = {
  width: 0,
  height: 0
}

const textStr = ref('')
const textSize = ref(3)
let transData = <imgComponent.localPixel[][]>[]
let drawColIndex = 0

// 绘制动作, 开始的地方
const drawer = () => {

  cacheCTX.clearRect(0, 0, canvasSize.width, canvasSize.height)
  showCTX.clearRect(0, 0, canvasSize.width, canvasSize.height)

  if (!textStr.value) { return }

  drawUpData( textStr.value )

  drawImg()
}

/** 准备像素数据 */
const drawUpData = (text: string) => {

  cacheCTX.fillText(text, 0, FONT_SIZE)
  const baseData = cacheCTX.getImageData(0, 0, canvasSize.width, canvasSize.height)

  transData.length = 0
  for (let i = 0; i < canvasSize.height; i += DIFF) {

    const localRow:imgComponent.localPixel[] = []
    transData.push(localRow)

    for (let j = 0; j < canvasSize.width; j += DIFF) {

      if (baseData.data[ (i + j * canvasSize.width) * DIFF + 3 ] > 0) {

        localRow.push({
          flag: true,
          itemX: i * textSize.value,
          itemY: j * textSize.value,
          color: getRandomColor(),
          size: getRandomSize()
        })

      } else {
        localRow.push({
          flag: false,
          itemX: 0,
          itemY: 0,
          color: '',
          size: 0
        })
      }
    }
  }

}

/** 绘制 */
const drawImg = () => {

  if (transData[0].length > drawColIndex++) {

    let localArr = transData[drawColIndex]
    if (localArr) {
      for (let i = 0; i < transData.length; i++) {
        const cachePoint = localArr[i]
        if (cachePoint.flag) {
          showCTX.beginPath()
          showCTX.arc(cachePoint.itemX, cachePoint.itemY, cachePoint.size, 0, 6.283185307179586)
          showCTX.fillStyle = cachePoint.color
          showCTX.fill()
        }
      }
    }

    requestAnimationFrame(drawImg)
  } else {
    drawColIndex = 0
  }
}

/** 随机十进制颜色 */
const getRandomColor = () => {
  const r = Math.floor(Math.random() * 256).toString(16).padStart(2, '0')
  const g = Math.floor(Math.random() * 256).toString(16).padStart(2, '0')
  const b = Math.floor(Math.random() * 256).toString(16).padStart(2, '0')

  return `#${r}${g}${b}`
}

/** 随机大小 */
const getRandomSize = () => {
  const result = Math.floor(Math.random() * 8) + 2
  return result
}

// 初始化画布
onMounted(() => {
  const { offsetWidth, offsetHeight } = <HTMLElement>document.getElementById('app-main')
  const { offsetHeight: setH } = <HTMLElement>document.querySelector('.text-img-operate')

  // 统一画布大小
  const localWidth = offsetWidth - 40
  const localHeight = offsetHeight - 60 - setH

  showCanvas = <HTMLCanvasElement>document.getElementById('text-img-canvas')
  showCanvas.width = localWidth
  showCanvas.height = localHeight

  showCTX = <CanvasRenderingContext2D>showCanvas.getContext('2d')

  Object.assign(canvasSize, {
    width: localWidth,
    height: localHeight
  })

  Object.freeze(canvasSize)

  cacheCanvas = document.createElement('canvas')
  cacheCanvas.height = localHeight
  cacheCanvas.width = localWidth

  cacheCTX = <CanvasRenderingContext2D>cacheCanvas.getContext('2d', { willReadFrequently: true })
  cacheCTX.font = `${FONT_SIZE}px Arial`

})

</script>

<style lang="scss" scoped>

canvas {
  border: 1px dashed;
}

.text-img {

  &-operate {
    height: 50px;

    label{
      margin-right: 20px;
    }
  }
}
</style>
